package org.reliablesource.jdt.actions;

import java.util.LinkedList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.reliablesource.jdt.model.ISourceElementInfo;
import org.reliablesource.jdt.model.SourceElementInfo;

/**
 * 
 * ReliableJDTCompilationUnitVisitor.java<br>
 * Copyright (c) 2007, Reliable Source, Inc. All Rights Reserved<br>
 * <br>
 * 
 * Created on: Jun 15, 2007 <br>
 * <br>
 * 
 * @author Dennis Park <a
 *         href="mailto:dennis.park@gmail.com">dennis.park@gmail.com</a>
 * 
 * @since 1.0.0
 */
public class ReliableJDTCompilationUnitVisitor extends ASTVisitor {
	final protected List<ISourceElementInfo> methodList;

	final protected List<ISourceElementInfo> fieldList;

//	final protected List<ISourceElementInfo> packageList;

	final protected List<ISourceElementInfo> importList;

	final protected ICompilationUnit compilationUnit;

	public ReliableJDTCompilationUnitVisitor(final ICompilationUnit _cu) {
		super();
		methodList = new LinkedList<ISourceElementInfo>();
		fieldList = new LinkedList<ISourceElementInfo>();
//		packageList = new LinkedList<ISourceElementInfo>();
		importList = new LinkedList<ISourceElementInfo>();
		compilationUnit = _cu;
	}

	/*
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
	 */
	public boolean visit(final MethodDeclaration _node) {
		ISourceElementInfo _methodElement;
		if (_node != null) {
			// Calculate total lines.
			Pattern _linesInFile = Pattern.compile("^", Pattern.MULTILINE); //$NON-NLS-1$
			int _startPos = _node.getStartPosition();

			String _src;
			try {
				_src = compilationUnit.getSource();
				Matcher _lineMatcher = _linesInFile.matcher(_src.substring(
						_startPos, _startPos + _node.getLength()));
				int _nLOC = 0;

				while (_lineMatcher.find())
					_nLOC++;

				_methodElement = new SourceElementInfo(_node.getName()
						.getFullyQualifiedName(), _nLOC);
				if (null != _node.resolveBinding())
					_methodElement.setJavaElement(_node.resolveBinding()
							.getJavaElement());

				methodList.add(_methodElement);

			} catch (JavaModelException e) {

			}
		}
		return super.visit(_node);
	}

	/*
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.FieldDeclaration)
	 */
	public boolean visit(final FieldDeclaration _node) {
		ISourceElementInfo _fieldElement;
		if (_node != null) {
			// Calculate total lines.
			Pattern _linesInFile = Pattern.compile("^", Pattern.MULTILINE); //$NON-NLS-1$
			int _startPos = _node.getStartPosition();

			String _src;
			try {
				_src = compilationUnit.getSource();
				Matcher _lineMatcher = _linesInFile.matcher(_src.substring(
						_startPos, _startPos + _node.getLength()));
				int _nLOC = 0;

				while (_lineMatcher.find())
					_nLOC++;

				String _id = ((VariableDeclarationFragment)_node.fragments().toArray()[0]).getName().getIdentifier();
				_fieldElement = new SourceElementInfo(_id, _nLOC);
				
				fieldList.add(_fieldElement);

			} catch (final JavaModelException e) {

			}
		}
		return super.visit(_node);
	}

	/*
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.AnonymousClassDeclaration)
	 */
	public boolean visit(AnonymousClassDeclaration node) {
		// don't dive into anonymous type declarations.
		return false;
	}

	/*
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.TypeDeclarationStatement)
	 */
	public boolean visit(TypeDeclarationStatement node) {
		// don't dive into local type declarations.
		return false;
	}

	/**
	 * @return the methodList
	 */
	public ISourceElementInfo[] getMethodList() {
		return methodList.toArray(new ISourceElementInfo[methodList.size()]);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.ImportDeclaration)
	 */
	@Override
	public boolean visit(final ImportDeclaration _node) {
		ISourceElementInfo _importElement;
		if (_node != null) {
			// Calculate total lines.
			Pattern _linesInFile = Pattern.compile("^", Pattern.MULTILINE); //$NON-NLS-1$
			int _startPos = _node.getStartPosition();

			String _src;
			try {
				_src = compilationUnit.getSource();
				Matcher _lineMatcher = _linesInFile.matcher(_src.substring(
						_startPos, _startPos + _node.getLength()));
				int _nLOC = 0;

				while (_lineMatcher.find())
					_nLOC++;

				_importElement = new SourceElementInfo(_node.getName().getFullyQualifiedName(), _nLOC);
				importList.add(_importElement);

			} catch (JavaModelException e) {

			}
		}
		return super.visit(_node);
	}

//	/*
//	 * (non-Javadoc)
//	 * 
//	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.Javadoc)
//	 */
//	@Override
//	public boolean visit(final Javadoc _node) {
//		return super.visit(_node);
//	}

//	/*
//	 * (non-Javadoc)
//	 * 
//	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.LineComment)
//	 */
//	@Override
//	public boolean visit(final LineComment _node) {
//
//		ISourceElementInfo _pkgElement;
//		if (_node != null) {
//			// Calculate total lines.
//			Pattern _linesInFile = Pattern.compile("^", Pattern.MULTILINE); //$NON-NLS-1$
//			int _startPos = _node.getStartPosition();
//
//			String _src;
//			try {
//				_src = compilationUnit.getSource();
//				Matcher _lineMatcher = _linesInFile.matcher(_src.substring(
//						_startPos, _startPos + _node.getLength()));
//				int _nLOC = 0;
//
//				while (_lineMatcher.find())
//					_nLOC++;
//
//				_pkgElement = new SourceElementInfo(_node.getLocationInParent()
//						.getId(), _nLOC);
//				packageList.add(_pkgElement);
//
//			} catch (JavaModelException e) {
//
//			}
//		}
//		return super.visit(_node);
//	}

//	/*
//	 * (non-Javadoc)
//	 * 
//	 * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.PackageDeclaration)
//	 */
//	@Override
//	public boolean visit(final PackageDeclaration _node) {
//		ISourceElementInfo _pkgElement;
//		if (_node != null) {
//			// Calculate total lines.
//			Pattern _linesInFile = Pattern.compile("^", Pattern.MULTILINE); //$NON-NLS-1$
//			int _startPos = _node.getStartPosition();
//
//			String _src;
//			try {
//				_src = compilationUnit.getSource();
//				Matcher _lineMatcher = _linesInFile.matcher(_src.substring(
//						_startPos, _startPos + _node.getLength()));
//				int _nLOC = 0;
//
//				while (_lineMatcher.find())
//					_nLOC++;
//
//				_pkgElement = new SourceElementInfo(_node.getLocationInParent()
//						.getId(), _nLOC);
//				packageList.add(_pkgElement);
//
//			} catch (JavaModelException e) {
//
//			}
//		}
//		return super.visit(_node);
//	}

	/**
	 * @return the fieldList
	 */
	public ISourceElementInfo[] getFieldList() {
		return fieldList.toArray(new ISourceElementInfo[fieldList.size()]);
	}

	/**
	 * @return the importList
	 */
	public ISourceElementInfo[] getImportList() {
		return importList.toArray(new ISourceElementInfo[importList.size()]);
	}

//	/**
//	 * @return the packageList
//	 */
//	public ISourceElementInfo[] getPackageList() {
//		return packageList.toArray(new ISourceElementInfo[packageList.size()]);
//	}
}